/******************************************************************************* * LogDruid : Generate charts and reports using data gathered in log files * Copyright (C) 2016 Frederic Valente (frederic.valente@gmail.com) * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. *******************************************************************************/ package logdruid.ui.table; import javax.swing.JPanel; import javax.swing.DefaultCellEditor; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextPane; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.text.DefaultHighlighter; import javax.swing.text.Highlighter; import org.apache.log4j.Logger; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.GridLayout; import java.text.ParseException; import org.apache.commons.lang3.time.FastDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; import logdruid.data.Repository; import logdruid.data.record.EventRecording; import logdruid.data.record.MetadataRecording; import logdruid.data.record.StatRecording; import logdruid.data.record.ReportRecording; import logdruid.data.record.Recording; import logdruid.data.record.RecordingItem; import logdruid.ui.RegexTableRenderer; import logdruid.util.DataMiner; import logdruid.util.PatternCache; import java.awt.Font; import javax.swing.ListSelectionModel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class ReportRecordingEditorTable extends JPanel { private static Logger logger = Logger.getLogger(DataMiner.class.getName()); private boolean DEBUG = false; static Matcher m; static ArrayList<RecordingItem> records = null; private MyTableModel model; private String[] header = { "Name", "Processing","Before", "Inside type", "Inside regex", "After", "Active", "Show", "Value" }; private ArrayList<Object[]> data = new ArrayList<Object[]>(); JTable table = null; private JTextPane examplePane; private Repository rep = null; private Recording recording; /** * @wbp.parser.constructor */ @SuppressWarnings("unchecked") public ReportRecordingEditorTable(JTextPane textPane) { super(new GridLayout(1, 0)); model = new MyTableModel(data, header,null); table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.setFont(new Font("SansSerif", Font.PLAIN, 11)); // table.setPreferredScrollableViewportSize(new Dimension(500, 200)); table.setPreferredScrollableViewportSize(table.getPreferredSize()); table.setFillsViewportHeight(true); textPane.getText(); this.examplePane = textPane; // Create the scroll pane and add the table to it. JScrollPane scrollPane = new JScrollPane(table); // Set up column sizes. initColumnSizes(table); // Fiddle with the type and processing column's cell editors/renderers. setUpProcessingColumn(table, table.getColumnModel().getColumn(1)); setUpTypeColumn(table, table.getColumnModel().getColumn(3)); setUpInsideRegexColumn(table, table.getColumnModel().getColumn(4)); setUpInsideRegexColumn(table, table.getColumnModel().getColumn(2)); setUpInsideRegexColumn(table, table.getColumnModel().getColumn(5)); // Add the scroll pane to this panel. add(scrollPane); //Add(); FixValues(); } public ReportRecordingEditorTable(Repository repo, Recording re, JTextPane textPane) { super(new GridLayout(1, 0)); this.examplePane = textPane; model = new MyTableModel(data, header,repo); table = new JTable(model); table.setPreferredScrollableViewportSize(new Dimension(500, 70)); table.setFillsViewportHeight(true); rep = repo; textPane.getText(); recording = re; // Create the scroll pane and add the table to it. JScrollPane scrollPane = new JScrollPane(table); // Set up column sizes. initColumnSizes(table); // Fiddle with the type and processing column's cell editors/renderers. setUpTypeColumn(table, table.getColumnModel().getColumn(3)); setUpProcessingColumn(table, table.getColumnModel().getColumn(1)); setUpInsideRegexColumn(table, table.getColumnModel().getColumn(4)); setUpInsideRegexColumn(table, table.getColumnModel().getColumn(2)); setUpInsideRegexColumn(table, table.getColumnModel().getColumn(5)); // Add the scroll pane to this panel. add(scrollPane); records = ((ReportRecording) re).getRecordingItem(); // Collections.sort(records); if (records != null) { Iterator it = records.iterator(); while (it.hasNext()) { RecordingItem rI = (RecordingItem) it.next(); String inside=""; inside= DataMiner.getMainRegex( rI.getType(),rI.getInside(), repo.getDateFormat(re.getDateFormatID())) ; logger.debug("inside: " + inside); data.add(new Object[] { rI.getName(), rI.getProcessingType(), rI.getBefore(), rI.getType(), inside,rI.getAfter(), rI.isSelected(),rI.isShow(), "" }); logger.debug("added: " + rI.getName()); } FixValues(); } } public void FixValues() { String patternString = ""; Matcher matcher = null; PatternCache patternCache=new PatternCache(); Iterator it = data.iterator(); Object[] obj; while (it.hasNext()) { obj = (Object[]) it.next(); String stBefore = (String) obj[2]; String stType = (String) obj[3]; String stInside = (String) obj[4]; String stAfter = (String) obj[5]; logger.debug("stType: " + stType); if (stType.equals("date") && rep.getDateFormat(recording.getDateFormatID()).getPattern() != null) { patternString += stBefore + "(" + rep.getDateFormat(recording.getDateFormatID()).getPattern() + ")" + stAfter; logger.debug("getTypeString(stType) getPattern -: " + rep.getDateFormat(recording.getDateFormatID()).getPattern()); logger.debug("getTypeString(stType) getDateFormat -: " + rep.getDateFormat(recording.getDateFormatID()).getDateFormat()); } else { if (stType.equals("manual")){ patternString += stBefore + "(" + stInside + ")" + stAfter; logger.debug("getTypeString(stType) -: " + stInside); }else{ patternString += stBefore + "(" + DataMiner.getTypeString(stType) + ")" + stAfter; logger.debug("getTypeString(stType) -: " + DataMiner.getTypeString(stType)); } } } try { logger.debug("theLine: " + examplePane.getText()); logger.debug("patternString: " + patternString); Highlighter h = examplePane.getHighlighter(); h.removeAllHighlights(); int currIndex = 0; String[] lines = examplePane.getText().split(System.getProperty("line.separator")); if (lines.length>=1){ for (int i=0; i<lines.length ; i++){ matcher = patternCache.getPattern(patternString,recording.isCaseSensitive()).matcher(lines[i]); if (matcher.find()) { // int currIndex = 0; // doc.insertString(doc.getLength(),line+"\n", null); for (int i2 = 1; i2 <= matcher.groupCount(); i2++) { model.setValueAt(matcher.group(i2), i2 - 1, 8); h.addHighlight(currIndex+matcher.start(i2), +currIndex+matcher.end(i2), new DefaultHighlighter.DefaultHighlightPainter(Color.ORANGE)); } } logger.debug("currIndex: " + currIndex + "matcher.end(i2): " + lines[i].length()+",l: "+lines[i]); currIndex += lines[i].length()+1 ; } } } catch (Exception e1) { e1.printStackTrace(); // System.exit(1); } } private void initColumnSizes(JTable theTable) { MyTableModel model = (MyTableModel) theTable.getModel(); TableColumn column = null; Component comp = null; int headerWidth = 0; int cellWidth = 0; TableCellRenderer headerRenderer = theTable.getTableHeader().getDefaultRenderer(); for (int i = 0; i < 9; i++) { column = theTable.getColumnModel().getColumn(i); comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0); headerWidth = comp.getPreferredSize().width; cellWidth = comp.getPreferredSize().width; if (DEBUG) { logger.debug("Initializing width of column " + i + ". " + "headerWidth = " + headerWidth + "; cellWidth = " + cellWidth); } column.setPreferredWidth(Math.max(headerWidth, cellWidth)); } } public void setUpProcessingColumn(JTable theTable, TableColumn typeColumn) { JComboBox functionComboBox = new JComboBox(); functionComboBox.addItem("capture"); functionComboBox.addItem("top100"); functionComboBox.addItem("sum"); typeColumn.setCellEditor(new DefaultCellEditor(functionComboBox)); DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); renderer.setToolTipText("Click for combo box"); typeColumn.setCellRenderer(renderer); } public void setUpInsideRegexColumn(JTable theTable, TableColumn typeColumn) { DefaultTableCellRenderer renderer = new RegexTableRenderer(); // renderer.setBackground(Color.GRAY); typeColumn.setCellRenderer(renderer); } public void setUpTypeColumn(JTable theTable, TableColumn typeColumn) { // Set up the editor for the type cells. JComboBox<String> comboBox = new JComboBox<String>(); comboBox.addItem("date"); comboBox.addItem("double"); comboBox.addItem("long"); comboBox.addItem("manual"); comboBox.addItem("percent"); comboBox.addItem("string"); comboBox.addItem("stringminimum"); comboBox.addItem("word"); typeColumn.setCellEditor(new DefaultCellEditor(comboBox)); // Set up tool tips for the type cells. DefaultTableCellRenderer renderer = new RegexTableRenderer(); renderer.setToolTipText("Click for combo box"); typeColumn.setCellRenderer(renderer); comboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JComboBox combo = (JComboBox) e.getSource(); Object selected = combo.getSelectedItem(); if (table.getSelectedRow()!=-1){ if(!model.getValueAt(table.getSelectedRow(), 3).equals("manual")) { // model.setValueAt(".*", table.getSelectedRow(), 4); logger.debug((String) model.getValueAt(table.getSelectedRow(), 3)); logger.debug((String) model.getValueAt(table.getSelectedRow(), 4)); model.setValueAt(DataMiner.getMainRegex( (String) selected.toString(),(String) model.getValueAt(table.getSelectedRow(), 4), rep.getDateFormat(recording.getDateFormatID())), table.getSelectedRow(), 4); model.fireTableCellUpdated(table.getSelectedRow(), 4); } else { logger.debug("here"); logger.debug((String) model.getValueAt(table.getSelectedRow(), 3)); logger.debug((String) model.getValueAt(table.getSelectedRow(), 4)); /* logger.debug(rep.getDateFormat(recording.getDateFormatID()));*/ logger.debug(DataMiner.getMainRegex( (String) selected.toString(),(String) model.getValueAt(table.getSelectedRow(), 4), rep.getDateFormat(recording.getDateFormatID()))); model.setValueAt(DataMiner.getMainRegex( (String) selected.toString(),(String) model.getValueAt(table.getSelectedRow(), 4), rep.getDateFormat(recording.getDateFormatID())), table.getSelectedRow(), 4); model.fireTableCellUpdated(table.getSelectedRow(), 4); } }} } ); } class MyTableModel extends AbstractTableModel { private String[] header; private ArrayList<Object[]> data; public MyTableModel(ArrayList<Object[]> data, String[] header,Repository rep) { this.header = header; this.data = data; } @Override public int getColumnCount() { if (header == null) { return 0; } else return header.length; } @Override public String getColumnName(int column) { return header[column]; } @Override public int getRowCount() { return data.size(); } @Override public Object getValueAt(int row, int column) { return data.get(row)[column]; } @Override public void setValueAt(Object value, int row, int column) { data.get(row)[column] = value; fireTableCellUpdated(row, column); } /* * JTable uses this method to determine the default renderer/ editor for * each cell. If we didn't implement this method, then the last column * would contain text ("true"/"false"), rather than a check box. */ public Class getColumnClass(int c) { if (getValueAt(0, c)!=null){ return getValueAt(0, c).getClass(); } else return String.class; } /* * Don't need to implement this method unless your table's editable. */ public boolean isCellEditable(int row, int col) { // Note that the data/cell address is constant, // no matt&er where the cell appears onscreen. if (col > 7) { return false; } else {if (col==4 && !data.get(row)[3].equals("manual")){ return false; } else{ return true; } } } } public ArrayList<RecordingItem> getRecordingItems() { ArrayList<RecordingItem> toReturn = new ArrayList<RecordingItem>(); for (int i = 0; i <data.size(); i++) { // model.getRowCount() logger.debug((String) model.getValueAt(i, 0)); //RecordingItem(String name, String before, String type, String processingType, String insideRegex, String after, Boolean isSelected, Boolean show, String value) { toReturn.add(new RecordingItem((String) model.getValueAt(i, 0), (String) model.getValueAt(i, 2), (String) model.getValueAt(i, 3), (String) model.getValueAt(i, 1), (String) model.getValueAt(i, 4),(String) model.getValueAt(i, 5), (Boolean) model.getValueAt(i, 6), (Boolean) model.getValueAt(i, 7), (String) model.getValueAt(i, 8))); //private String[] header = { "Name", "Processing", "Before", "Inside type", "Inside regex", "After", "Active", "Show", "Value" }; // rI.getName(), rI.getProcessingType(), rI.getBefore(), rI.getType(), inside,rI.getAfter(), rI.isSelected(),rI.isShow(), "" }); } return toReturn; } public void Add() { data.add(new Object[] { "default", "capture", ".*", "long", DataMiner.getTypeString("long"), "", Boolean.TRUE, Boolean.TRUE,"" }); table.repaint(); } public void Insert() { data.add(((table.getSelectedRow() != -1) ? table.convertRowIndexToModel(table.getSelectedRow()) : -1), new Object[] { "default", "capture", ".*", "long", DataMiner.getTypeString("long"),"", Boolean.TRUE, Boolean.TRUE, "" }); table.repaint(); } public void Remove() { data.remove(((table.getSelectedRow() != -1) ? table.convertRowIndexToModel(table.getSelectedRow()) : -1)); table.repaint(); } }